package net.hn.hnms.biz.gasext.dws.service.impl;


import com.alibaba.excel.util.DateUtils;
import com.baomidou.dynamic.datasource.annotation.DS;
import net.hn.hnms.biz.api.mine.RemoteMineInfoService;
import net.hn.hnms.biz.api.mine.model.dto.MineCodeMapDto;
import net.hn.hnms.biz.api.safety.gasext.domain.MineLeaderInfoVo;
import net.hn.hnms.biz.api.safety.gasext.domain.OverstaffingSituationDwsVo;
import net.hn.hnms.biz.api.safety.gasext.domain.PersonnelMonitoringVo;
import net.hn.hnms.biz.api.safety.gasext.domain.TrailVo;
import net.hn.hnms.biz.api.safety.gasext.domain.dto.LeadInfoDto;
import net.hn.hnms.biz.api.safety.location.model.LeadVo;
import net.hn.hnms.biz.gasext.dws.domain.RydwRyjzPo;
import net.hn.hnms.biz.gasext.dws.domain.RydwRyssPo;
import net.hn.hnms.biz.gasext.dws.domain.RydwRyxxPo;
import net.hn.hnms.biz.gasext.dws.domain.dto.PeopleAndleadNumberVo;
import net.hn.hnms.biz.gasext.dws.domain.fineData.DwmcEntity;
import net.hn.hnms.biz.gasext.dws.domain.fineData.InsertShiftManage1Po;
import net.hn.hnms.biz.gasext.dws.domain.fineData.ShiftManagementPo;
import net.hn.hnms.biz.gasext.dws.mapper.*;
import net.hn.hnms.biz.gasext.dws.service.AqjkService;
import net.hn.hnms.biz.gasext.dws.service.DwdRydwService;
import net.hn.hnms.biz.gasext.dws.service.FineDataService;
import net.hn.hnms.biz.gasext.dws.service.RydwService;
import net.hn.hnms.sys.common.core.utils.StringUtils;
import net.hn.hnms.sys.common.redis.domain.SysOrganization;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 查询dws 人员定位数据数据
 */
@Service
@DS(value = "dwsLocation")
public class RydwServiceImpl implements RydwService {


    @Resource
    private RemoteMineInfoService remoteMineInfoService;

    @Resource
    private AqjkService aqjkService;

    @Resource
    private RydwRyssMapper rydwRyssMapper;


    @Resource
    private RydwRyxxMapper rydwRyxxMapper;

    @Resource
    private FineDataService fineDataService;

    @Resource
    private RydwRyjzMapper rydwRyjzMapper;

    @Resource
    private DwdRydwService dwdRydwService;

    @Resource
    private DwdRydwRyssHMapper dwdRydwRyssHMapper;
    @Resource
    private DwdCoalMineProduceDurationRtDMapper dwdCoalMineProduceDurationRtDMapper;
    /**
     * 大屏首页-超员情况
     * @return
     */
    @Override
    public List<OverstaffingSituationDwsVo> getOverstaffingSituation() {
        //获取煤矿 地址灾害类型及核定人数
        List<MineCodeMapDto> mineCodeMapList = remoteMineInfoService.getMineCodeMapList(null);
        //将list 转成map
        Map<String, MineCodeMapDto> map = mineCodeMapList.stream().collect(Collectors.toMap(MineCodeMapDto::getMineCode, p -> Optional.ofNullable(p).orElse(new MineCodeMapDto())));

        //获取煤矿列表
        //获取所有煤矿
        List<SysOrganization> list = aqjkService.selectCodeSubMineList();
        List<OverstaffingSituationDwsVo> vos = list.stream().map(t -> {
            OverstaffingSituationDwsVo vo = new OverstaffingSituationDwsVo();
            //获取当前煤矿井下人数
            Integer personNumber =rydwRyssMapper.selectPersonNumberList(t.getOrgCode());
            vo.setMineCode(t.getOrgCode());
            vo.setMineName(t.getOrgName());
            MineCodeMapDto mineCodeMapDto = map.get(t.getOrgCode());
            if (mineCodeMapDto != null) {
                vo.setHazardType(mineCodeMapDto.getMineHazardType());
                vo.setMineMaxPeopleNumber(mineCodeMapDto.getMineMaxPeopleNumber());
            } else {
                vo.setHazardType("---");
                vo.setMineMaxPeopleNumber(0);

            }
            vo.setNowNumber(personNumber);

            //预警状态
            String state = null;
            //核定人数-实时人数 大于等于零  正常
            if (Optional.ofNullable(vo.getMineMaxPeopleNumber()).orElse(0)- vo.getNowNumber() >= 0) {
                state = "正常";
            } else {
                state = "超员";
            }
            vo.setWarningState(state);
            return vo;
        }).collect(Collectors.toList());
        return vos;
    }

    /**
     * 大屏首页-人员检测
     * @return
     */
    @Override
    public PersonnelMonitoringVo getPersonnelMonitoring() {
        PersonnelMonitoringVo vo=new PersonnelMonitoringVo();

        //获取所有煤矿
        List<SysOrganization> list = aqjkService.selectCodeSubMineList();

        List<MineLeaderInfoVo> vos = list.stream().map(t -> {
            MineLeaderInfoVo leaderInfoVo = new MineLeaderInfoVo();
            //获取当前煤矿井下人数
            Integer personNumber =rydwRyssMapper.selectPersonNumberList(t.getOrgCode());
            leaderInfoVo.setMineCode(t.getOrgCode());
            leaderInfoVo.setMineName(t.getOrgName());

            leaderInfoVo.setMineNowNumber(personNumber);


            //获取帆软带值班领导信息
            //值班领导名称集合
            TreeSet<String> duty = new TreeSet<>();
            //值班备注信息
            TreeSet<String> shift = new TreeSet<>();
            //获取帆软煤矿名称
            List<DwmcEntity> fineListByCode = fineDataService.getFineListByCode(t.getOrgCode());
            //有数据  且三级煤矿名称不为空
            if (fineListByCode != null && fineListByCode.size() > 0 && fineListByCode.get(0).getFourdw() != null) {
                //帆软煤矿名称
                String mineName = fineListByCode.get(0).getFourdw();
                //获取带值班表
                List<ShiftManagementPo> fineDataBeOnWatchListBymineName = fineDataService.getFineDataBeOnWatchListBymineName(mineName);
                //判断值班是否是 全天
                Boolean dutyIsAllDay = false;
                for (ShiftManagementPo tt : fineDataBeOnWatchListBymineName) {//值班类型  有值 并且是全天
                    if (tt.getClasses1() != null && "全天".equals(tt.getClasses1())) {
                        dutyIsAllDay = true;
                        break; // 提前结束循环
                    }
                }

                if (dutyIsAllDay) {
                    // 值班是全天
                    for (ShiftManagementPo tt : fineDataBeOnWatchListBymineName) {//值班类型  有值 并且是全天
                        if (StringUtils.isNotBlank(tt.getLeader1())) {
                            duty.add(tt.getLeader1());
                        }
                    }
                    //赋值班次
                    leaderInfoVo.setDutyClass("全天");
                } else {
                    //区分 早班 中班 晚班  后夜班
                    //获取班次时间
                    List<InsertShiftManage1Po> fineDataClassListBymineName = fineDataService.getFineDataClassListBymineName(mineName);
                    //早班开始时间
                    List<String> morningTime = new ArrayList<>();
                    //中班开始时间
                    List<String> middleTime = new ArrayList<>();
                    //晚班开始时间
                    List<String> nightTime = new ArrayList<>();
                    //后夜班开始时间
                    List<String> afterNightTime = new ArrayList<>();

                    if (!fineDataClassListBymineName.isEmpty()) {
                        if (StringUtils.isNotBlank(fineDataClassListBymineName.get(0).getMornStart()) && StringUtils.isNotBlank(fineDataClassListBymineName.get(0).getMornStop())){
                            morningTime.add(fineDataClassListBymineName.get(0).getMornStart());
                            morningTime.add(fineDataClassListBymineName.get(0).getMornStop());
                        }
                        if (StringUtils.isNotBlank(fineDataClassListBymineName.get(0).getMidStart()) && StringUtils.isNotBlank(fineDataClassListBymineName.get(0).getMidStop())){
                            middleTime.add(fineDataClassListBymineName.get(0).getMidStart());
                            middleTime.add(fineDataClassListBymineName.get(0).getMidStop());
                        }
                        if (StringUtils.isNotBlank(fineDataClassListBymineName.get(0).getEvenStart()) && StringUtils.isNotBlank(fineDataClassListBymineName.get(0).getEvenStop())){
                            nightTime.add(fineDataClassListBymineName.get(0).getEvenStart());
                            nightTime.add(fineDataClassListBymineName.get(0).getEvenStop());
                        }
                        if (StringUtils.isNotBlank(fineDataClassListBymineName.get(0).getEvenLstart()) && StringUtils.isNotBlank(fineDataClassListBymineName.get(0).getEvenLstop())) {
                            afterNightTime.add(fineDataClassListBymineName.get(0).getEvenLstart());
                            afterNightTime.add(fineDataClassListBymineName.get(0).getEvenLstop());
                        }
                    }
                    //时间段集合
                    Map<String, List<String>> clases = new HashMap<>();
                    clases.put("早", morningTime);
                    clases.put("中", middleTime);
                    clases.put("晚", nightTime);
                    clases.put("夜", afterNightTime);
                    //判断现在时间是数据那个班
                    String nowTime = DateUtils.format(new Date(), "HH:mm");
                    String dutyclass1 = this.determineShift(nowTime, clases);
                    // 使用 Java Stream 过滤出包含 classes2 包含 "早班" 的集合
                    //赋值班次
                    leaderInfoVo.setDutyClass(dutyclass1);

                    List<ShiftManagementPo> filteredList = fineDataBeOnWatchListBymineName.stream()
                            .filter(po -> po.getClasses1() != null && po.getClasses1().contains(dutyclass1))
                            .collect(Collectors.toList());
                    //遍历集合  值班查出当前班次所有领导集合
                    filteredList.forEach(po -> {
                        if (StringUtils.isNotBlank(po.getLeader1())) {
                            //领导不是空的
                            duty.add(po.getLeader1());
                        }
                    });
                }


                //帆软带班领导 名称集合 获取带班名称
                fineDataBeOnWatchListBymineName.forEach(tt -> {
                    //获取所有的带班领导 不区分早中晚夜班
                    //取出来的数据 领导名称集合与dws精准人员定位取交集
                    if (StringUtils.isNotBlank(tt.getLeader2())) {
                        //领导不是空的
                        shift.add(tt.getLeader2());
                    }

                });
            }



            //获取dws井下带班领导入井信息
            List<LeadVo> leads = rydwRyssMapper.selectLeadPitInfo(t.getOrgCode());

            List<LeadVo> remark = leads;
            //dws 精准人员定位获取的矿领导与帆软填报带班领导求交集
            //如果存在相同的姓名则需要 否则将剔除
            leads.removeIf(tt -> !shift.contains(tt.getName()));

            //补充领导基本信息
            List<LeadInfoDto> leadInfoDtos = leads.stream().map(tt -> {
                LeadInfoDto leadInfoDto = new LeadInfoDto();
                BeanUtils.copyProperties(tt, leadInfoDto);
                //获取人员信息
                RydwRyxxPo rydwRyxxPo=rydwRyxxMapper.selectMaxDateInfo(t.getOrgCode(), leadInfoDto.getCode());
                if (rydwRyxxPo != null) {
                    //职务
                    leadInfoDto.setPosition(rydwRyxxPo.getZw());
                    //部门名称
                    leadInfoDto.setDeptName(rydwRyxxPo.getDzbzbm());
                } else {
                    leadInfoDto.setPosition("---");
                    leadInfoDto.setDeptName("---");
                }

                return leadInfoDto;
            }).collect(Collectors.toList());

            //带班领导姓名
            //数据不为空
            leads.forEach(m -> {
                if (StringUtils.isBlank(leaderInfoVo.getShiftLeader())) {
                    //是空的 第一次 追加
                    leaderInfoVo.setShiftLeader(m.getName());
                } else {
                    //第二次 追加 前面携带逗号
                    leaderInfoVo.setShiftLeader(leaderInfoVo.getShiftLeader() + "," + m.getName());
                }
            });
            leaderInfoVo.setLeaderInfo(leadInfoDtos);


            //帆软值班领导
            AtomicReference<String> dutyString = new AtomicReference<>("");
            duty.forEach(tt -> {
                if (StringUtils.isBlank(dutyString.get())) {
                    //是空的 第一次 追加
                    dutyString.set(tt);
                } else {
                    //第二次 追加 前面携带逗号
                    dutyString.set(dutyString.get() + "," + tt);
                }
            });
            //设置值班领导
            leaderInfoVo.setDutyLeader(dutyString.get());

            //实际井下矿领导  读取所有姓名放入备注里面
            AtomicReference<String> remarkLeaderString = new AtomicReference<>("");
            remark.forEach(tt -> {
                if (StringUtils.isBlank(remarkLeaderString.get())) {
                    //是空的 第一次 追加
                    remarkLeaderString.set(tt.getName());
                } else {
                    //第二次 追加 前面携带逗号
                    remarkLeaderString.set(remarkLeaderString.get()+ "," + tt.getName());
                }
            });
            //存放备注
            leaderInfoVo.setRemark("DWS井下领导名称集合：" + remarkLeaderString.get());
            return leaderInfoVo;
        }).collect(Collectors.toList());


        //总人数
        // 计算总人数
        int totalMineNowNumber = vos.stream()
                .mapToInt(MineLeaderInfoVo::getMineNowNumber)  // 提取每个对象的现有人数
                .sum();  // 对现有人数进行求和


        //计算带班领导数
        int sum = 0;
        for (MineLeaderInfoVo mineLeaderInfoVo : vos) {
            //遍历所有煤矿带班领导
            if ( StringUtils.isNotEmpty(mineLeaderInfoVo.getShiftLeader())){
                //带班字段不为空
                String shiftLeader = mineLeaderInfoVo.getShiftLeader();
                if (shiftLeader.contains(",")) {
                    //存在逗号
                    String[] split = shiftLeader.split(",");
                    for (String s : split) {
                        sum++;
                    }
                } else {
                    //不存在逗号   直接加 1
                    sum++;
                }
            }
        }
        //带班领导数
        vo.setShiftLeaderNumber(sum);
        //总人数
        vo.setLeaderSum(totalMineNowNumber);


        //井下人数  downholeMan;
        //露天矿
        //魏家峁 150622B0012000210118
        // 铧尖  未知
        // 伊敏  150724B0012000510053
        List<String> codesToRemove = Arrays.asList("150622B0012000210118", "150724B0012000510053");
        //（去除露天矿）
        List<MineLeaderInfoVo> downholeManVos = vos.stream()
                .filter(dto -> !codesToRemove.contains(dto.getMineCode()))
                .collect(Collectors.toList());
        int downholeMan = downholeManVos.stream()
                .mapToInt(MineLeaderInfoVo::getMineNowNumber)  // 提取每个对象的现有人数
                .sum();  // 对现有人数进行求和

        // 坑下人数 pitDownMan;
        //（仅有露天矿） 魏家峁 铧尖 伊敏
        List<MineLeaderInfoVo> pitDownManVos = vos.stream()
                .filter(dto -> codesToRemove.contains(dto.getMineCode()))
                .collect(Collectors.toList());
        int pitDownMan = pitDownManVos.stream()
                .mapToInt(MineLeaderInfoVo::getMineNowNumber)  // 提取每个对象的现有人数
                .sum();  // 对现有人数进行求和



        //坑下人数
        vo.setPitDownMan(pitDownMan);
        //井下人数
        vo.setDownholeMan(downholeMan);
        //煤矿领导及人数信息列表
        vo.setMineLeaderInfoList(vos);
        return vo;
    }

    /**
     * 人员入井后轨迹
     * @param staffCode
     * @param inTime
     * @param mineCode
     * @return
     */
    @Override
    public List<TrailVo> trail(String staffCode, String inTime, String mineCode) {
        List<TrailVo> vos = new ArrayList<>();

        //查询实时表  获取实时表内人员信息
        RydwRyssPo rydwRyssPo = rydwRyssMapper.selectTrail(staffCode, inTime, mineCode);
        if (rydwRyssPo == null) {
            return new ArrayList<>();
        }
        //查询当前煤矿下所有基站
        List<RydwRyjzPo> rydwRyjzPos = rydwRyjzMapper.selectStationListByMineCode(mineCode);
        //转成map
        Map<String, RydwRyjzPo> rydwRyjzPoMap = rydwRyjzPos.stream()
                .collect(Collectors.toMap(
                        RydwRyjzPo::getJzbm, // 键为 jzbm 属性
                        p -> Optional.ofNullable(p).orElse(new RydwRyjzPo()), // 值为 RydwRyjzPo 对象，处理可能为空的情况
                        (existing, replacement) -> existing)); // 解决重复键冲突的策略，保留已存在的值

        //获取的轨迹字段集合
        String xjgjjzsjjh = rydwRyssPo.getXjgjjzsjjh();
        //根据逗号拆分 每一个分站
        String[] split = xjgjjzsjjh.split(",");
        for (String s : split) {
            TrailVo trailVo = new TrailVo();
            //根据& 区分编码和时间
            String[] split1 = s.split("&");
            String stationCode = split1[0];
            String inStationCodeTime = split1[1];
            //获取分站详情
            RydwRyjzPo rydwRyjzPo = rydwRyjzPoMap.get(stationCode);
            trailVo.setSubstationCode(stationCode);
            trailVo.setInTime(inStationCodeTime);
            if (rydwRyjzPo != null) {
                trailVo.setSubstationName(rydwRyjzPo.getJzmc() + "_" + rydwRyjzPo.getWzzs());
                trailVo.setCoordinate_x(rydwRyjzPo.getXzb());
                trailVo.setCoordinate_y(rydwRyjzPo.getYzb());
                trailVo.setCoordinate_z(rydwRyjzPo.getZzb());
            } else {
                trailVo.setSubstationName("---");
                trailVo.setCoordinate_x("0");
                trailVo.setCoordinate_y("0");
                trailVo.setCoordinate_z("0");
            }
            vos.add(trailVo);
        }

        // 倒序操作
//        Collections.reverse(vos);

        return vos;
    }

    @Override
    public RydwRyssPo selectTrail(String staffCode, String inTime, String mineCode) {
        RydwRyssPo rydwRyssPo = rydwRyssMapper.selectTrail(staffCode, inTime, mineCode);
        return rydwRyssPo;
    }

    /**
     * 煤矿分站列表
     * @param mineCode
     * @return
     */
    @Override
    public List<RydwRyjzPo> selectStationListByMineCode(String mineCode) {
        List<RydwRyjzPo> list = rydwRyjzMapper.selectStationListByMineCode(mineCode);

        return list;
    }

    /**
     * 煤矿井下带班领导
     * @param mineCode
     * @return
     */
    @Override
    public List<LeadVo> selectLeadPitInfo(String mineCode) {
        List<LeadVo> leadVos = rydwRyssMapper.selectLeadPitInfo(mineCode);
        return leadVos;
    }

    /**
     * 获取当前煤矿的井下人数和带班领导数
     * @param mineCode
     * @return
     */
    @Override
    public PeopleAndleadNumberVo getPeopleAndleadNumberByMineCode(String mineCode) {
        PeopleAndleadNumberVo vo = new PeopleAndleadNumberVo();
        Integer integer = dwdRydwRyssHMapper.selectPersonNumberList(mineCode);
        vo.setPeopleNumber(integer.toString());
        TreeSet<String> mindutyList = dwdRydwService.getMindutyList(mineCode);
        vo.setLead(mindutyList);
        return vo;
    }

    // 判断当前时间属于哪个班次的方法
    private String determineShift(String nowTime, Map<String, List<String>> clases) {
        String shift = "";
        for (Map.Entry<String, List<String>> entry : clases.entrySet()) {
            String key = entry.getKey();
            List<String> value = entry.getValue();
            if (value.isEmpty() || value.size() != 2) {
                //不用判断  没有时间段  直接跳过比较
                continue;
            }
            boolean between = this.isBetween(nowTime, value);
            if (between) {
                shift = key;
            }
        }
        return shift;
    }

    // 辅助方法，判断时间是否在指定范围内
    private boolean isBetween(String nowTime,List<String> times) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
            String startTime = times.get(0);
            String endTime = times.get(1);
            Date now = sdf.parse(nowTime);
            Date start = sdf.parse(startTime);
            Date end = sdf.parse(endTime);

            // 如果结束时间跨越了午夜边界  0：00
            if (end.before(start)) {
                Calendar endCal = Calendar.getInstance();
                endCal.setTime(end);
                endCal.add(Calendar.DAY_OF_MONTH, 1); // 添加一天
                end = endCal.getTime();
            }

            // 判断当前时间是否在开始时间和结束时间之间
            return now.compareTo(start) >= 0 && now.compareTo(end) < 0;
        } catch (ParseException e) {
            e.printStackTrace();
            return false;
        }
    }
}
